var llmHistoryAnswerIndex = 0
var knowledgebaseHistoryAnswerIndex = 0
var llmHistory = []
var knowledgebaseHistory = []
var tipllmFlag = 1
var tipknowledgebaseFlag = 1
var tipfileFlag = 1
var stream = {
  locked: false
}
var controller
var signal
var slider
var form
var flow
var score_slider
var isInitSlider = false
var temperature = 0.1
var score_threshold = 1
var G_modelName
var G_promptName = ''
var G_lastQuery
var dropdown
var element
var isMouseScroll = false
$(document).ready(function () {
  initLayui()
  initModelList()
  initRoleList()
  addWheelEvent('answer-llm')
  addWheelEvent('answer-knowledgebase')
})

function initLayui() {
  $('#query').val('')
  layui.use(function () {
    slider = layui.slider;
    form = layui.form;
    flow = layui.flow;
    dropdown = layui.dropdown;
    element = layui.element;

    var temperature_slider = slider.render({

      elem: '#slider',

      tips: true, // 开启提示文本

      // tipsAlways: true, // 开启始终显示提示文本

      min: 0, // 最小值

      max: 200, // 最大值
      step: 1,
      value: 10,
      setTips: function (value) { // 自定义提示文本

        return value / 100;

      },
      done: function (value) {

        temperature = value / 100

      }

    });

    // 输入框点缀事件
    form.on('input-affix(release)', function (data) {
      var index = $('.center-btns-item.active').data('index')
      var value = data.elem.value;
      G_lastQuery = value
      $('#retalk-btn').hide()
      if (value) {
        $('#query').val('')
        var history_len = $('#history-len').val()
        if (stream.locked) {
          controller.abort();
        }
        var userMessage = ` <div style="padding: 0.2rem;">
                              <img src="../static/img/icon10.png" style="width:.23rem;height:.23rem;margin-right:.1rem">
                              ${value}
                            </div>`
        switch (index) {
          case 1:
            tipllmFlag = 0
            $('#tip-llm').hide()
            $('#answer-llm').append(userMessage);
            var params = {
              "query": G_promptName + value,
              "conversation_id": "",
              "history_len": history_len,
              "history": llmHistory,
              "stream": true,
              "model_name": G_modelName,
              "temperature": temperature,
              "max_tokens": 0,
              "prompt_name": 'default'
            }
            $('#stop-btn').show()
            getLLMResponse(params, value)
            break
          case 2:
            if ($('#knowledgebase-select').val()) {
              tipknowledgebaseFlag = 0
              $('#tip-knowledgebase').hide()
              $('#answer-knowledgebase').append(userMessage);
              var params = {
                "query": G_promptName + value,
                "knowledge_base_name": $('#knowledgebase-select').val(),
                "top_k": $('#knowledge-len').val(),
                "score_threshold": score_threshold, //知识库匹配相关度阈值，取值范围在0-1之间，SCORE越小，相关度越高，取到1相当于不筛选，建议设置在0.5左右
                "history": knowledgebaseHistory,
                "stream": true,
                "model_name": G_modelName,
                "temperature": temperature,
                "max_tokens": 0,
                "prompt_name": 'default'
              }
              $('#stop-btn').show()
              getKnowledgebaseResponse(params, value)
            } else {
              layer.msg('请先在右侧选择知识库！')
            }

            break
          case 3:
            tipfileFlag = 0
            $('#tip-knowledgebase').hide()
            var userMessage = ` <div style="padding: 0.2rem;">
                                  <img src="../static/img/icon10.png" style="width:.23rem;height:.23rem;margin-right:.1rem">
                                  ${value}
                                </div>`
            $('#answer-llm').append(userMessage);
            var params = {
              "query": G_promptName + value,
              "conversation_id": "",
              "history_len": history_len,
              "history": llmHistory,
              "stream": true,
              "model_name": G_modelName,
              "temperature": temperature,
              "max_tokens": 0,
              "prompt_name": 'default'
            }
            getLLMResponse(params, value)
            break
        }
      } else {
        layer.msg('请输入您想要提问的问题')
      }


      return false;
    });

    // 导出记录
    form.on('submit(export)', function (data) {
      exportData()
      return false;
    })

    // 清空记录
    form.on('submit(clear)', function (data) {
      clearData()
      return false;
    })

    // 保存知识库
    form.on('submit(edit-form)', function (data) {
      $('#query').val(data.field.content)
      $('.layui-icon-release').click()
      layer.closeAll()
      return false;
    })

  })
}

function initRoleList(roleId) {
  AjaxRequest('/chat/role/list?orderType=2', callBack)

  function callBack(result) {
    if (result.status == 200) {
      var data = result.result

      var moreData = []
      if (roleId) {
        var str = `<div class="right-btns-item" data-id="" data-promptname="">清空</div>`
        $.each(data, function (i, e) {
          if (e.id == roleId) {
            moveToFront(data, e);
            $.each(data, function (a, b) {
              if (a == 4 && data.length > 5) {
                moreData = data.slice(4);
                str += `<div id="dropdown-role" class="right-btns-item dropdown-menu" data-promptname="查看更多">更多</div>`
                return false
              } else {
                str += `<div class="right-btns-item ${a == 0 ? 'active' : ''}" data-id="${b.id}" data-promptname="${b.prompt}">
                ${b.name}
              </div>`
              }
            })
            return
          }
        })
      } else {
        var str = `<div class="right-btns-item active" data-id="" data-promptname="">清空</div>`
        $.each(data, function (i, e) {
          if (i == 4 && data.length > 5) {
            moreData = data.slice(4);
            str += `<div id="dropdown-role" class="right-btns-item dropdown-menu" data-promptname="查看更多">更多</div>`
            return false
          } else {
            str += `<div class="right-btns-item" data-id="${e.id}" data-promptname="${e.prompt}">
            ${e.name}
          </div>`
          }

        })
      }

      $('#flow-role').empty().append(str)
      showMoreRole(moreData)
      $('.right-btns-item').click(function (e) {
        if (e.currentTarget.innerHTML != '更多') {
          G_promptName = e.currentTarget.dataset.promptname
          $(e.currentTarget).addClass('active').siblings().removeClass('active')
          initQuestionList()
        }
      })
      $('.right-btns-item').on('mouseenter', function (e) {
        if (e.currentTarget.innerHTML != '清空' && e.currentTarget.innerHTML != '更多') {
          layer.tips(e.currentTarget.dataset.promptname, e.currentTarget, {
            tips: 1
          });
        }
      }).on('mouseleave', function () {
        layer.closeLast('tips');
      });
    } else {
      layer.msg('查询失败')
    }
  }

  setTimeout(() => {
    initQuestionList()
  }, 200);
}

function showMoreRole(data) {
  var content = ''
  $.each(data, function (i, e) {
    content += `<li data-id="${e.id}" data-promptname="${e.prompt}" class="more-item">
                  <div class="layui-menu-body-title">${e.name}</div>
                </li>`
  })
  dropdown.render({
    elem: '#dropdown-role',
    content: `<ul class="layui-menu layui-dropdown-menu">
                ${content}
              </ul>`,
    ready: function () {
      $('.more-item').on('mouseenter', function (e) {
        layer.tips(e.currentTarget.dataset.promptname, e.currentTarget, {
          tips: 1,
        });
      }).on('mouseleave', function () {
        layer.closeLast('tips');
      });
    },
    click: function (data, othis) {
      layer.closeLast('tips');
      G_promptName = othis[0].dataset.promptname
      initRoleList(othis[0].dataset.id)
      // console.log(data); // 当前所点击的菜单项对应的数据
      // console.log(this.elem); // 当前组件绑定的目标元素对象，批量绑定中常用
    }
  })

}

function moveToFront(array, element) {
  const index = array.indexOf(element);
  if (index > -1) {
    array.splice(index, 1); // 移除元素
    array.unshift(element); // 将元素插入数组开头
  }
}

function initModelList() {
  $.ajax({
    url: '/langchain' + '/llm_model/list_running_models',
    type: 'post',
    contentType: "application/json",
    // data: JSON.stringify(res.engName),
    success: function (result) {
      var code = result.code
      if (code == 200) {
        var data = result.data
        for (let key in data) {
          G_modelName = key
        }
        var modelArr = [{
            name: 'DT-6B',
            value: 'chatglm3-6b'
          },
          {
            name: 'DT-14B',
            value: 'Qwen1.5-14B-Chat'
          },
          {
            name: 'DT-34B',
            value: 'Yi-34B-Chat-4bits'
          },
          {
            name: 'DT-law',
            value: 'law_llama3'
          },
        ]
        dropdown.render({
          elem: '#dropdown-menu',
          // trigger: 'click' // trigger 已配置在元素 `lay-options` 属性上
          data: [{
              title: modelArr[0].name,
              id: modelArr[0].value,
              templet: `{{= d.title }} ${G_modelName == modelArr[0].value ? '<i class="layui-icon layui-icon-ok"></i>' : ''}`
            }, {
              title: modelArr[1].name,
              id: modelArr[1].value,
              templet: `{{= d.title }} ${G_modelName == modelArr[1].value ? '<i class="layui-icon layui-icon-ok"></i>' : ''}`
            },
            {
              title: modelArr[2].name,
              id: modelArr[2].value,
              templet: `{{= d.title }} ${G_modelName == modelArr[2].value ? '<i class="layui-icon layui-icon-ok"></i>' : ''}`
            },
            {
              title: modelArr[3].name,
              id: modelArr[3].value,
              templet: `{{= d.title }} ${G_modelName == modelArr[3].value ? '<i class="layui-icon layui-icon-ok"></i>' : ''}`
            }
          ],
          click: function (data, othis) {
            layer.load(0)
            var params = {
              model_name: G_modelName,
              new_model_name: data.id,
            }
            $.ajax({
              url: '/langchain' + '/llm_model/change',
              type: 'post',
              contentType: "application/json",
              data: JSON.stringify(params),
              success: function (result) {
                var code = result.code
                if (code == 200) {
                  layer.closeAll()
                  G_modelName = data.id
                  dropdown.reload('dropdown-menu', {
                    data: [{
                      title: modelArr[0].name,
                      id: modelArr[0].value,
                      templet: `{{= d.title }} ${G_modelName == modelArr[0].value ? '<i class="layui-icon layui-icon-ok"></i>' : ''}`
                    }, {
                      title: modelArr[1].name,
                      id: modelArr[1].value,
                      templet: `{{= d.title }} ${G_modelName == modelArr[1].value ? '<i class="layui-icon layui-icon-ok"></i>' : ''}`
                    }, {
                      title: modelArr[2].name,
                      id: modelArr[2].value,
                      templet: `{{= d.title }} ${G_modelName == modelArr[2].value ? '<i class="layui-icon layui-icon-ok"></i>' : ''}`
                    }, {
                      title: modelArr[3].name,
                      id: modelArr[3].value,
                      templet: `{{= d.title }} ${G_modelName == modelArr[3].value ? '<i class="layui-icon layui-icon-ok"></i>' : ''}`
                    }],
                  });
                  layer.msg('已切换为：' + data.title + '模型')
                }
              }
              // console.log(data); // 当前所点击的菜单项对应的数据
              // console.log(othis); // 当前所点击的菜单项元素对象
              // console.log(this.elem); // 当前组件绑定的目标元素对象，批量绑定中常用
            })
          }
        })
      }
    }
  })
}

// 初始化常用问题列表
function initQuestionList() {
  $('#flow-question').empty()
  flow.load({
    elem: '#flow-question', // 流加载容器
    scrollElem: '#flow-question',
    // isAuto: false,
    // isLazyimg: true,
    // end: " ",
    done: function (page, next) { // 加载下一页
      var lis = []
      var chatRoleId = $('.right-btns-item.active').data('id')

      AjaxRequest('/chat/question/list/page?orderType=2&pageSize=20&pageNum=' + page + '&chatRoleId=' + chatRoleId, callBack)

      function callBack(result) {
        if (result.status == 200) {
          var data = result.result.data
          $.each(data, function (i, e) {
            lis.push(`<div class="right-cards-item" onclick="chatWithModel('${e.content.replace(/\n/g, "")}')">
                        <div style="padding: .1rem .1rem .3rem .1rem;">
                          <div class="right-cards-item-content">${e.name}</div>
                          <div class="edit-btn" onclick="editWithModel(event,'${e.content}')" title="编辑">
                            <i class="layui-icon layui-icon-edit" style="font-size: .25rem;"></i>
                          </div>
                        </div>

                      </div>`)
          })

          next(lis.join(''), page < result.result.total / 20);
          handlerData()
        } else {
          layer.msg('查询失败')
        }
      }
    }
  });
}

function chatWithModel(query) {
  $('#query').val(query)
  // $('.layui-icon-release').click()
}

function editWithModel(event, content) {
  layer.open({
    type: 1,
    shadeClose: false,
    move: false,
    closeBtn: 2,
    skin: 'default-layer',
    area: ['6rem', 'auto'],
    title: '编辑',
    content: `<div class="layui-form" lay-filter="saveForm" style="padding: .2rem;color:#E4EFFF">
                <div class="layui-form-item">
                  <div style="margin-top: .1rem;">
                    <textarea type="text" name="content" lay-verify="required" class="layui-textarea">
                    </textarea>
                  </div>
                </div>
                <div class="layui-form-item" style="text-align:center">
                  <button type="submit" class="layui-btn layui-btn-lg layui-bg-blue" lay-submit lay-filter="edit-form" style="border-radius:.08rem">保  存</button>
                </div>
              </div>`,
    success: function (layero, index) {
      form.val("saveForm", {
        "content": content,
      });
    }
  })
  event.stopPropagation()
}

// llm对话
async function getLLMResponse(content, query) {
  isMouseScroll = false
  scrollTop('answer-llm')
  //创建实例
  var converter = new showdown.Converter();
  var url = '/langchain' + '/chat/chat';
  var str = ''

  llmHistoryAnswerIndex++
  $('#answer-llm').append(` <div class="answer-card" >
                              <img src="../static/img/icon11.png" style="width:.23rem;height:.23rem;margin-right:.1rem">
                              <div id="llmHistory-${llmHistoryAnswerIndex}" style="width: 100%;">
                                <img class="icon-loading" src="../static/img/loading.gif">
                              </div>
                            </div>`)
  controller = new AbortController();
  signal = controller.signal;
  const response = await fetch(url, {
    method: 'POST',
    headers: {
      "Content-Type": "application/json",
    },
    body: JSON.stringify(content),
    signal
  });
  // 设置Response Type为stream
  stream = response.body;
  // 创建一个TextDecoderStream对象
  const decoder = new TextDecoderStream();
  // 从流中读取文本内容
  const reader = stream.pipeThrough(decoder).getReader();

  while (true) {
    try {
      const result = await reader.read();
      if (!result.done) {
        if (result.value.indexOf('data: {"text"') > -1) { //llm回答
          var text = JSON.parse(result.value.split('data: ')[1]).text
          str += text
          var html = converter.makeHtml(str);
          $('#llmHistory-' + llmHistoryAnswerIndex)[0].innerHTML = html.replaceAll('\n', '')
          if (!isMouseScroll) {
            scrollTop('answer-llm')
          }
        }
      } else {

        llmHistory.push({
          role: "user",
          content: query
        })
        $('#stop-btn').hide()
        var text = $('#llmHistory-' + llmHistoryAnswerIndex).text()
        $('#llmHistory-' + llmHistoryAnswerIndex).append(`<img class="copy-icon" src="../static/img/icon19.svg" title="点击复制" onclick="copyText('${'llmHistory-' + llmHistoryAnswerIndex}')">`)
        scrollTop('answer-llm')
        if (text) {
          var length = $('#history-len').val()
          llmHistory.push({
            "role": "assistant",
            "content": text
          })
          if (llmHistory.length > (length * 2)) {
            llmHistory = llmHistory.slice(-(length * 2))
          }
          break;
        } else {
          layer.msg('模型连接失败，请退出系统重新登陆，或者刷新界面')
          break;
        }
      }
    } catch (error) {
      $('#stop-btn').hide()
      // console.error("Error reading from the stream", error);
      console.log("流失请求被中断");
      break;
    }
  }
}

function copyText(domId) {
  // 获取div中的文本内容
  var text = document.getElementById(domId).innerText;

  // 创建一个临时的输入框来存储文本
  var input = document.createElement("input");
  input.value = text;

  // 将输入框添加到页面，并选中文本
  document.body.appendChild(input);
  input.select();

  // 执行复制操作
  var msg = document.execCommand("copy");
  if (msg) {
    layer.msg("拷贝成功")
  }

  // 移除临时输入框
  document.body.removeChild(input);
}

// 知识库对话
async function getKnowledgebaseResponse(content, query) {
  isMouseScroll = false
  scrollTop('answer-knowledgebase')
  //创建实例
  var converter = new showdown.Converter();
  var url = '/langchain' + '/chat/knowledge_base_chat';
  var str = ''
  var matchStr = ''

  knowledgebaseHistoryAnswerIndex++
  $('#answer-knowledgebase').append(` <div class="answer-card" >
                                        <img src="../static/img/icon11.png" style="width:.23rem;height:.23rem;margin-right:.1rem">
                                        <div style="width: 100%;" id="knowledgebaseHistory-${knowledgebaseHistoryAnswerIndex}">
                                          <img class="icon-loading" src="../static/img/loading.gif">
                                        </div>
                                      </div>`)
  controller = new AbortController();
  signal = controller.signal;
  const response = await fetch(url, {
    method: 'POST',
    headers: {
      "Content-Type": "application/json",
    },
    body: JSON.stringify(content),
    signal,
  });
  // 设置Response Type为stream
  stream = response.body;
  // 创建一个TextDecoderStream对象
  const decoder = new TextDecoderStream();
  // 从流中读取文本内容
  const reader = stream.pipeThrough(decoder).getReader();

  // stream = response.body.getReader()

  while (true) {
    try {
      const result = await reader.read();
      // console.log(result)
      if (!result.done) {
        if (result.value.indexOf(': ping -') > -1) {

        } else if (result.value.indexOf('data: {"answer"') > -1) { //知识库问答
          var text = JSON.parse(result.value.split('data: ')[1]).answer
          str += text
          var html = converter.makeHtml(str);
          $('#knowledgebaseHistory-' + knowledgebaseHistoryAnswerIndex)[0].innerHTML = html.replaceAll('\n', '')
          if (!isMouseScroll) {
            scrollTop('answer-knowledgebase')
          }
        } else if (result.value.indexOf('data: {"docs":') > -1) { //知识库匹配文档
          matchStr += result.value
        } else {
          matchStr += result.value
        }
      } else {
        var text = JSON.parse(matchStr.split('data: ')[1]).docs
        if (text[0].indexOf('未找到相关文档') > -1) {
          text[0] = "<span style='color:rgb(1, 170, 237)'>未找到相关文档,该回答为大模型自身能力解答！</span>"
          str += '<br><br>知识库匹配结果：<br>'
          str += text
        } else {
          str += `<br><br>
            <div class="layui-collapse" lay-filter="filter-collapse">
              <div class="layui-colla-item">
                <div class="layui-colla-title">知识库匹配结果：</div>
                <div class="layui-colla-content">${text}</div>
              </div>
            </div>`
        }
        var html = converter.makeHtml(str);
        $('#knowledgebaseHistory-' + knowledgebaseHistoryAnswerIndex)[0].innerHTML = html.replaceAll('\n', '')
        element.render('collapse', 'filter-collapse');
        knowledgebaseHistory.push({
          role: "user",
          content: query
        })
        $('#stop-btn').hide()
        var text = $('#knowledgebaseHistory-' + knowledgebaseHistoryAnswerIndex).text().split('知识库匹配结果')[0]
        $('#knowledgebaseHistory-' + knowledgebaseHistoryAnswerIndex).append(`<img class="copy-icon" src="../static/img/icon19.svg" title="点击复制" onclick="copyText('${'knowledgebaseHistory-' + knowledgebaseHistoryAnswerIndex}')">`)
        setTimeout(() => {
          scrollTop('answer-knowledgebase')
        }, 100);

        if (text) {
          var length = $('#history-len').val()
          knowledgebaseHistory.push({
            "role": "assistant",
            "content": text
          })
          if (knowledgebaseHistory.length > (length * 2)) {
            knowledgebaseHistory.slice(-(length * 2))
          }
          break;
        } else {
          layer.msg('模型连接失败，请退出系统重新登陆，或者刷新界面')
          break;
        }

      }
    } catch (error) {
      console.log(error)
      $('#stop-btn').hide()
      // console.error("Error reading from the stream", error);
      // console.log("流失请求被中断");
      break;
    }
  }
}

// 中间块按钮切换
$('.center-btns-item').click(function (e) {
  var index = e.currentTarget.getAttribute("data-index")
  $(e.currentTarget).addClass('active').siblings().removeClass('active')
  switch (index) {
    case "1":
      if (tipllmFlag == 0) {
        $('#tip-llm').hide()
      } else {
        $('#tip-llm').show()
      }
      $('#tip-knowledgebase').hide()
      $('#tip-file').hide()
      $('#knowledgebase-setting').hide()
      $('#answer-llm').show()
      $('#answer-knowledgebase').hide()
      $('#answer-file').hide()
      $('.right-cards').css('height', '54%')
      break;
    case "2":
      $('#tip-llm').hide()
      if (tipknowledgebaseFlag == 0) {
        $('#tip-knowledgebase').hide()
      } else {
        $('#tip-knowledgebase').show()
      }
      $('#tip-file').hide()
      $('#knowledgebase-setting').show()
      $('#answer-llm').hide()
      $('#answer-knowledgebase').show()
      $('#answer-file').hide()
      $('.right-cards').css('height', '32%')
      initKnowledgebaseSelect()
      if (!isInitSlider) {
        score_slider = slider.render({

          elem: '#score-slider',

          tips: true, // 开启提示文本

          // tipsAlways: true, // 开启始终显示提示文本

          min: 0, // 最小值

          max: 200, // 最大值
          step: 1,
          value: 100,
          setTips: function (value) { // 自定义提示文本

            return value / 100;

          },
          done: function (value) {

            score_threshold = value / 100

          }

        });
        isInitSlider = true
      }
      break;
    case "3":
      $('#tip-llm').hide()
      $('#tip-knowledgebase').hide()
      if (tipfileFlag == 0) {
        $('#tip-file').hide()
      } else {
        $('#tip-file').show()
      }
      $('#knowledgebase-setting').hide()
      $('#answer-llm').hide()
      $('#answer-knowledgebase').hide()
      $('#answer-file').show()
      break;
  }
})

// 初始化知识库下拉
function initKnowledgebaseSelect() {
  AjaxRequest('/kb/select', callBack)

  function callBack(result) {
    if (result.status == 200) {
      var data = result.result
      var str = '<option value="">请选择知识库</option>'
      $.each(data, function (i, e) {
        str += `<option value="${e.engName}">${e.name}</option>`
      })
      $('#knowledgebase-select').empty().append(str)
      form.render()
    } else {
      layer.msg('查询失败')
    }
  }
}

function autoLinkify(input) {
  let output = input;

  // 正则表达式匹配 URL
  const urlRegex = /(\b(https?|ftp):\/\/[-A-Z0-9+&@#\/%?=~_|!:,.;]*[-A-Z0-9+&@#\/%=~_|])/gim;

  // 使用正则表达式替换匹配到的 URL 为超链接
  output = output.replace(urlRegex, function (url) {
    return `<a href='${url}' target='_blank' style="color: rgb(1, 170, 237);">点击查看</a>`;
  });

  return output;
}

let searchInput = document.getElementById('query');
searchInput.addEventListener('keyup', function (event) {
  if (event.keyCode === 13) {
    $('.layui-icon-release').click()
  }
});

// 导出对话
function exportData(params) {
  var index = $('.center-btns-item.active').data('index')
  switch (index) {
    case 1:
      var contentNode = $('#answer-llm').clone()
      break
    case 2:
      var contentNode = $('#answer-knowledgebase').clone()
      break
  }
  data = wordExport(contentNode)
  downLoad(data, '历史记录')
}

// 清空对话
function clearData() {
  var index = $('.center-btns-item.active').data('index')
  switch (index) {
    case 1:
      $('#answer-llm').empty()
      llmHistory = []
      break
    case 2:
      $('#answer-knowledgebase').empty()
      knowledgebaseHistory = []
      break
  }
}

function wordExport(contentNode) {
  var static = {
    mhtml: {
      top: "Mime-Version: 1.0\nContent-Base: " + location.href +
        "\nContent-Type: Multipart/related; boundary=\"NEXT.ITEM-BOUNDARY\";type=\"text/html\"\n\n--NEXT.ITEM-BOUNDARY\nContent-Type: text/html; charset=\"utf-8\"\nContent-Location: " +
        location.href + "\n\n<!DOCTYPE html>\n<html>\n_html_</html>",
      head: "<head>\n<meta http-equiv=\"Content-Type\" content=\"text/html; charset=utf-8\">\n<style>\n_styles_\n</style>\n</head>\n",
      body: "<body>_body_</body>"
    }
  };
  var options = {
    maxWidth: 624
  };
  // Clone selected element before manipulating it
  var markup = $(contentNode).clone();
  // Remove hidden elements from the output
  markup.each(function () {
    var self = $(contentNode);
    if (self.is(':hidden'))
      self.remove();
  });

  // Embed all images using Data URLs
  var images = Array();
  var img = markup.find('img');
  for (var i = 0; i < img.length; i++) {
    // Calculate dimensions of output image
    var w = Math.min(img[i].width, options.maxWidth);
    var h = img[i].height * (w / img[i].width);
    // Create canvas for converting image to data URL
    var canvas = document.createElement("CANVAS");
    canvas.width = w;
    canvas.height = h;
    // Draw image to canvas
    var context = canvas.getContext('2d');
    context.drawImage(img[i], 0, 0, w, h);
    // Get data URL encoding of image
    var uri = canvas.toDataURL("image/png");
    $(img[i]).attr("src", img[i].src);
    img[i].width = w;
    img[i].height = h;
    // Save encoded image to array
    images[i] = {
      type: uri.substring(uri.indexOf(":") + 1, uri.indexOf(";")),
      encoding: uri.substring(uri.indexOf(";") + 1, uri.indexOf(",")),
      location: $(img[i]).attr("src"),
      data: uri.substring(uri.indexOf(",") + 1)
    };
  }

  // Prepare bottom of mhtml file with image data
  var mhtmlBottom = "\n";
  for (var i = 0; i < images.length; i++) {
    mhtmlBottom += "--NEXT.ITEM-BOUNDARY\n";
    mhtmlBottom += "Content-Location: " + images[i].location + "\n";
    mhtmlBottom += "Content-Type: " + images[i].type + "\n";
    mhtmlBottom += "Content-Transfer-Encoding: " + images[i].encoding + "\n\n";
    mhtmlBottom += images[i].data + "\n\n";
  }
  mhtmlBottom += "--NEXT.ITEM-BOUNDARY--";

  //TODO: load css from included stylesheet
  var styles = "";

  // Aggregate parts of the file together
  var fileContent = static.mhtml.top.replace("_html_", static.mhtml.head.replace("_styles_", styles) + static
    .mhtml
    .body.replace("_body_", markup.html())) + mhtmlBottom;

  // Create a Blob with the file contents
  var blob = new Blob([fileContent], {
    type: "application/msword;charset=utf-8"
  });
  return fileContent
};

/*
wps:kswps
docx:msword
*/
function downLoad(data, fileName) {
  let blob = new Blob([data], {
    type: "application/msword"
  });
  let url = URL.createObjectURL(blob);
  let link = document.createElement('a');
  link.setAttribute("href", url);
  link.setAttribute("download", `${fileName}.doc`);
  link.style.visibility = 'hidden';
  document.body.appendChild(link);
  link.click();
  document.body.removeChild(link);
}

function scrollTop(domId) {
  // 滚动到底部
  var myDiv = document.getElementById(domId)
  myDiv.scrollTop = myDiv.scrollHeight;

}

function addWheelEvent(domId) {
  // 获取div元素
  var myDiv = document.getElementById(domId);

  // 为div添加鼠标滚轮事件监听器
  myDiv.addEventListener('wheel', function (event) {
    // 检查是否接近底部
    if (this.scrollHeight - (this.scrollTop + this.offsetHeight) < 30 && event.wheelDelta < 0) {
      isMouseScroll = false
    } else {
      isMouseScroll = true
    }
  })
}

// 停止对话
function stopTalk() {
  controller.abort()
  $('#retalk-btn').show()
}

// 重新生成
function reTalk() {
  chatWithModel(G_lastQuery)
}

/**
 * 数据处理-卡片位置计算
 * TODO 数据量大时分页渲染
 * */
function handlerData() {
  // 1、获取容器宽
  let contentWidth = document.getElementsByClassName('right-cards')[0].clientWidth;

  // 2、卡片
  let div = document.getElementsByClassName('right-cards-item')

  // 初始卡片宽、边距
  let normalWidth = 100,
    padding = 10

  // 每排可以放多少个
  // let page = Math.floor((contentWidth) / normalWidth)
  let page = 2

  // 自适应宽
  let nowWidth = contentWidth / page

  // 初始化width、left、top
  // for (let i = 0; i < div.length; i++) {
  //   div[i].style.cssText = `left:0;top:0;`
  // }

  let divHeight = []

  // 设置第一排的left
  for (let i = 0; i < page; i++) {
    div[i].style.cssText = `width:${nowWidth - padding + 'px'};left:${i * nowWidth + 'px'};`
    divHeight.push(div[i].clientHeight + 0)
  }

  // 其他卡片的top、left
  for (let i = page; i < div.length; i++) {
    let min_height = Math.min.apply(Math, divHeight), // 获取到数组中最小top
      min_index = divHeight.indexOf(min_height) // 查找到最小高度卡片的下标
    div[i].style.width = nowWidth - padding + 'px';
    div[i].style.left = div[min_index].style.left // 当前卡片和最小高度卡片的left值相同
    div[i].style.top = min_height + padding + 'px'

    // 替换的高度 = 上一个卡片的top + 最小高度卡片的height + 间隙
    divHeight[min_index] = min_height + div[i].clientHeight + padding
  }
}

$('.example-item').click(function (e) {
  var query = $(this).children().last()[0].innerText
  $('#query').val(query)
  $('.layui-icon-release').click()
})